const Asset = require('./Asset');
const OrderBook = require('./OrderBook');
const MacroEvent = require('./MacroEvent');
const InvestorGenerator = require('../investors/InvestorGenerator');
const Order = require('./Order');

/**
 * 金融市场环境核心类
 * 管理资产、订单簿、时间推进等核心功能
 */
class MarketEnvironment {
  /**
   * @param {Object} config - 市场配置参数
   */
  constructor(config = {}) {
    this.assets = new Map();
    this.orderBooks = new Map();
    this.investors = new Map();
    this.time = 0;
    this.macroEvents = [];
    this.activeEvents = [];
    this.investorGenerator = new InvestorGenerator(config.investorGeneratorConfig);
    this.config = {
      initialAssets: config.initialAssets || [],
      timeStep: config.timeStep || 1,
      macroEventProbability: config.macroEventProbability || 0.05,
      ...config
    };
  }

  /**
   * 添加资产到市场
   * @param {Asset} asset - 资产对象
   */
  addAsset(asset) {
    this.assets.set(asset.id, asset);
    this.orderBooks.set(asset.id, new OrderBook(asset.id));
  }

  /**
   * 添加投资者到市场
   * @param {Investor} investor - 投资者对象
   */
  addInvestor(investor) {
    this.investors.set(investor.id, investor);
  }

  /**
   * 移除投资者
   * @param {string} investorId - 投资者ID
   */
  removeInvestor(investorId) {
    this.investors.delete(investorId);
  }

  /**
   * 添加宏观事件
   * @param {MacroEvent} event - 宏观事件
   */
  addMacroEvent(event) {
    this.macroEvents.push(event);
  }

  /**
   * 提交订单
   * @param {Order} order - 订单对象
   */
  submitOrder(order) {
    const orderBook = this.orderBooks.get(order.assetId);
    if (orderBook) {
      orderBook.addOrder(order);
    } else {
      throw new Error(`Asset ${order.assetId} not found`);
    }
  }

  /**
   * 获取资产价格
   * @param {string} assetId - 资产ID
   * @returns {number} 资产价格
   */
  getAssetPrice(assetId) {
    const asset = this.assets.get(assetId);
    return asset ? asset.getPrice() : null;
  }

  /**
   * 获取所有资产价格
   * @returns {Map} 资产价格映射
   */
  getAllAssetPrices() {
    const prices = new Map();
    for (const [id, asset] of this.assets) {
      prices.set(id, asset.getPrice());
    }
    return prices;
  }

  /**
   * 检查是否触发宏观事件
   */
  checkForMacroEvents() {
    // 检查现有事件是否结束
    this.activeEvents = this.activeEvents.filter(event => event.update());

    // 有一定概率触发新事件
    if (Math.random() < this.config.macroEventProbability && this.macroEvents.length > 0) {
      // 随机选择事件类型：1-只影响资产1，2-只影响资产2，3-影响两个资产
      const eventType = Math.floor(Math.random() * 3) + 1;
      const assetIds = Array.from(this.assets.keys());
      
      // 根据事件类型筛选事件
      let eligibleEvents = [];
      if (assetIds.length >= 2) {
        if (eventType === 1) {
          // 只影响资产1的事件
          eligibleEvents = this.macroEvents.filter(event => 
            event.targetAssets === assetIds[0] || 
            (Array.isArray(event.targetAssets) && event.targetAssets.includes(assetIds[0])) ||
            event.targetAssets === 'all'
          );
        } else if (eventType === 2) {
          // 只影响资产2的事件
          eligibleEvents = this.macroEvents.filter(event => 
            event.targetAssets === assetIds[1] || 
            (Array.isArray(event.targetAssets) && event.targetAssets.includes(assetIds[1])) ||
            event.targetAssets === 'all'
          );
        } else if (eventType === 3) {
          // 影响两个资产的事件
          eligibleEvents = this.macroEvents.filter(event => 
            event.targetAssets === 'all' ||
            (Array.isArray(event.targetAssets) && 
             event.targetAssets.includes(assetIds[0]) && 
             event.targetAssets.includes(assetIds[1]))
          );
        }
      } else {
        eligibleEvents = this.macroEvents;
      }

      // 如果有符合条件的事件，则随机选择一个
      if (eligibleEvents.length > 0) {
        const event = eligibleEvents[Math.floor(Math.random() * eligibleEvents.length)];
        event.activate();
        this.activeEvents.push(event);
        console.log(`\n!!! 宏观事件触发: ${event.name} (影响: ${event.impact}) !!!\n`);
      }
    }
  }

  /**
   * 应用宏观事件影响
   */
  applyMacroEffects() {
    // 对每个活跃事件，更新资产价格
    for (const event of this.activeEvents) {
      for (const [id, asset] of this.assets) {
        const impact = event.getAssetImpact(id);
        if (impact !== 0) {
          const currentPrice = asset.getPrice();
          const newPrice = currentPrice * (1 + impact * 0.01); // 影响幅度限制在1%以内
          // 添加一些随机波动
          const volatility = asset.config.volatility || 0.02;
          const randomFactor = 1 + (Math.random() - 0.5) * volatility;
          const finalPrice = newPrice * randomFactor;
          asset.updatePrice(finalPrice, this.time, Math.floor(Math.random() * 1000));
        }
      }
    }
    
    // 实现资产对冲机制
    this.applyHedgingMechanism();
  }

  /**
   * 应用资产对冲机制
   */
  applyHedgingMechanism() {
    const assetIds = Array.from(this.assets.keys());
    if (assetIds.length >= 2) {
      // 获取两个资产
      const asset1 = this.assets.get(assetIds[0]);
      const asset2 = this.assets.get(assetIds[1]);
      
      const price1 = asset1.getPrice();
      const price2 = asset2.getPrice();
      
      // 如果一个资产价格上涨，另一个资产价格下跌（实现对冲）
      const change1 = price1 - asset1.history[Math.max(0, asset1.history.length - 2)].close;
      const change2 = price2 - asset2.history[Math.max(0, asset2.history.length - 2)].close;
      
      // 如果两个资产同向变动，引入对冲机制
      if ((change1 > 0 && change2 > 0) || (change1 < 0 && change2 < 0)) {
        // 以一定概率触发对冲机制
        if (Math.random() < 0.3) {
          // 使一个资产价格上涨，另一个下跌，实现对冲效果
          if (change1 > 0) {
            // asset1 上涨，asset2 下跌
            asset1.updatePrice(price1 * (1 + Math.random() * 0.01), this.time, Math.floor(Math.random() * 500));
            asset2.updatePrice(price2 * (1 - Math.random() * 0.01), this.time, Math.floor(Math.random() * 500));
          } else {
            // asset1 下跌，asset2 上涨
            asset1.updatePrice(price1 * (1 - Math.random() * 0.01), this.time, Math.floor(Math.random() * 500));
            asset2.updatePrice(price2 * (1 + Math.random() * 0.01), this.time, Math.floor(Math.random() * 500));
          }
        }
      }
    }
  }

  /**
   * 生成新投资者
   */
  generateNewInvestors() {
    const newInvestor = this.investorGenerator.generateInvestor();
    if (newInvestor) {
      this.addInvestor(newInvestor);
      console.log(`\n>>> 新${newInvestor.getType()}入场: ${newInvestor.name} <<<\n`);
    }
  }

  /**
   * 处理止盈止损
   */
  processTakeProfitAndStopLoss() {
    const marketPrices = this.getAllAssetPrices();
    
    for (const [_, investor] of this.investors) {
      if (investor.getIsBankrupt()) continue;
      
      const assetsToClose = investor.checkTakeProfitAndStopLoss(marketPrices);
      
      for (const { assetId } of assetsToClose) {
        const position = investor.getPosition(assetId);
        if (position.quantity > 0) {
          const assetPrice = marketPrices.get(assetId) || 0;
          // 创建市价卖出订单
          const order = new Order(
            investor.id,
            assetId,
            'sell',
            assetPrice,
            position.quantity
          );
          this.submitOrder(order);
        }
      }
    }
  }

  /**
   * 导出所有订单簿数据
   * @returns {Object} 所有订单簿数据
   */
  exportAllOrderBooks() {
    const exportedData = {};
    for (const [assetId, orderBook] of this.orderBooks) {
      exportedData[assetId] = orderBook.exportOrderBook();
    }
    return exportedData;
  }

  /**
   * 推进市场时间
   */
  advanceTime() {
    this.time += this.config.timeStep;
    
    // 生成新投资者
    this.generateNewInvestors();
    
    // 检查宏观事件
    this.checkForMacroEvents();
    
    // 应用宏观影响
    this.applyMacroEffects();
    
    // 处理止盈止损
    this.processTakeProfitAndStopLoss();
    
    // 让每个投资者做出决策
    for (const [_, investor] of this.investors) {
      const order = investor.decide(this);
      if (order) {
        this.submitOrder(order);
      }
    }
  }

  /**
   * 获取市场状态快照
   * @returns {Object} 市场状态
   */
  getSnapshot() {
    const snapshot = {
      time: this.time,
      assets: {},
      orderBooks: {},
      investors: {},
      activeEvents: this.activeEvents.map(e => ({
        name: e.name,
        type: e.type,
        impact: e.impact,
        remainingDuration: e.remainingDuration
      }))
    };

    // 获取资产状态
    for (const [id, asset] of this.assets) {
      snapshot.assets[id] = {
        id: asset.id,
        name: asset.name,
        price: asset.getPrice(),
        history: asset.getHistory()
      };
    }

    // 获取订单簿状态
    for (const [assetId, orderBook] of this.orderBooks) {
      snapshot.orderBooks[assetId] = orderBook.getSnapshot();
    }

    // 获取投资者状态
    for (const [id, investor] of this.investors) {
      snapshot.investors[id] = {
        id: investor.id,
        name: investor.name,
        type: investor.getType(),
        capital: investor.capital,
        positions: Array.from(investor.positions),
        totalValue: investor.getTotalValue(this.getAllAssetPrices())
      };
    }

    return snapshot;
  }
}

module.exports = MarketEnvironment;